package cybertechcebu.task
{
	import cybertechcebu.Console;
	import cybertechcebu.FTPClient;
	import cybertechcebu.FTPCommand;
	import cybertechcebu.FTPResponse;
	import cybertechcebu.LocalFile;
	import cybertechcebu.enum.Commands;
	import cybertechcebu.enum.Responses;
	
	import flash.events.Event;
	import flash.net.FileReference;
	import flash.utils.ByteArray;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;
	import flash.utils.setTimeout;
	
	import mx.controls.Alert;

	public class FileUploadTask extends Task
	{
		private var fileRef:FileReference;
		private var localFile:LocalFile;
		private var interval:uint;
		private var fileContents:ByteArray;
		private var bufferSize:uint = 1048576; //65536
		private var smallerBufferSize:uint = 4096; //8192;
		private var timeout:uint = 300;
		private var fileSize:uint;
		private var sendWholeThreshold:uint = 8388608; //8 mb
		private var changeBufferSizeThreshold:uint = 100000000; //100mb

		public function FileUploadTask(client:FTPClient, localFile:LocalFile)
		{
			super(client);
			this.localFile = localFile;
			this.fileRef = localFile.fileRef;
		}

		override protected function startTask():void
		{
			sendCommand(new FTPCommand(Commands.PASV));
			sendCommand(new FTPCommand(Commands.STOR, fileRef.name));
		}

		override public function handleResponse(response:FTPResponse):void
		{
			switch (response.code)
			{
				case Responses.ENTERING_PASV:
	
					createDataSocket(response);
					
					break;
				case Responses.DATA_CONN_CLOSE:
					
					break;
				case Responses.FILE_STATUS_OK:

					break
				case Responses.NOT_FOUND:
					
					break;
				default:
					dispatchTaskError("Unhandled response code: " + response.code);
			}
		}

		private function createDataSocket(response:FTPResponse):void
		{					
		
			initDataSocket();
			
			addConnectHandler(function(e:Event):void
			{
				startSendingFile();
			});
			
			connect(response.str);			
			
		}

		private function startSendingFile():void
		{
			fileContents = fileRef.data;
			fileSize = fileRef.size;
		
			if (fileSize < sendWholeThreshold)
			{
				sendFileImmediately();
			}
			else
			{

				if (fileSize > changeBufferSizeThreshold)
				{
					bufferSize = smallerBufferSize;
				}

				interval = setInterval(sendFilePart, timeout);
			}
		}

		private function sendFileImmediately():void
		{
			dataSocket.writeBytes(fileContents, 0, fileSize);
			dataSocket.flush();
			Console.progress("Sending file: " + fileRef.name + " -- " + fileContents.length + " bytes");
			setTimeout(cleanUp, timeout);
		}

		private function sendFilePart():void
		{
			Console.progress("Sending file: " + fileRef.name + " -- bytes remaining - " + fileContents.bytesAvailable);
			if (fileContents.bytesAvailable <= 0 || !dataSocket.connected)
			{
				clearInterval(interval);
				setTimeout(cleanUp, timeout);
			}
			else
			{
				var buffer:ByteArray = new ByteArray();
				fileContents.readBytes(buffer, 0, bufferSize);
				dataSocket.writeBytes(buffer, 0, buffer.bytesAvailable);
				dataSocket.flush();
				if (fileContents.bytesAvailable < bufferSize)
					bufferSize = fileContents.bytesAvailable;

			}
		}

		private function cleanUp():void
		{
			dataSocket.close();
			dispatchTaskEnd(true);
		}
	}
}
